`timescale 1ns/1ps
//in wrapper ,all control signals active high
//2048*128 = 4*512*128
//modify wea00/wea01/wea10/wea11
module ram_dp_d2048_w128_wrapper (clka,clkb,wea,web,addra,addrb,dina,dinb,douta,doutb,ram_dp_cfg_register);
  input  clka;
  input  clkb;
  input [11:0] ram_dp_cfg_register;
  input  wea;//write enable,active high
  input  web; 
  input [10:0] addra;
  input [10:0] addrb;
  input [127:0] dina;
  input [127:0] dinb;
  output wire[127:0] douta;//rdata
  output reg [127:0] doutb;

wire sela00,selb00;
wire sela01,selb01;
wire sela10,selb10;
wire sela11,selb11;

reg cena00,cenb00;
reg cena01,cenb01;
reg cena10,cenb10;
reg cena11,cenb11;

reg cena00_ff,cenb00_ff;
reg cena01_ff,cenb01_ff;
reg cena10_ff,cenb10_ff;
reg cena11_ff,cenb11_ff;

wire [127:0]  doutb00;
wire [127:0]  doutb01;
wire [127:0]  doutb10;
wire [127:0]  doutb11;

assign douta = 128'b0;

assign sela00 = (addra[10:9] == 2'b00);
assign sela01 = (addra[10:9] == 2'b01);
assign sela10 = (addra[10:9] == 2'b10);
assign sela11 = (addra[10:9] == 2'b11);

assign selb00 = (addrb[10:9] == 2'b00);
assign selb01 = (addrb[10:9] == 2'b01);
assign selb10 = (addrb[10:9] == 2'b10);
assign selb11 = (addrb[10:9] == 2'b11);


  // read data valid flag
  always @ (posedge clka) begin 
    cena00_ff <= cena00;
    cena01_ff <= cena01;
    cena10_ff <= cena10;
    cena11_ff <= cena11;
  end

  always @ (posedge clkb) begin 
    cenb00_ff <= cenb00;
    cenb01_ff <= cenb01;
    cenb10_ff <= cenb10;
    cenb11_ff <= cenb11;
  end

  // read data choose
  always @(*) begin
    case ({cenb11_ff,cenb10_ff,cenb01_ff,cenb00_ff})
      4'b0001: begin 
        doutb = doutb00;
      end
      4'b0010: begin 
        doutb = doutb01;
      end
      4'b0100: begin 
        doutb = doutb10;
      end
      4'b1000: begin 
        doutb = doutb11;
      end
      default : begin
        doutb = 'b0;
      end
    endcase
  end

  //write first
  always@(*)begin
    if((addra == addrb)) begin
      case({wea,web}) 
	      2'b00:begin//(rd a&b) 
		      cena00 = sela00;
	        cenb00 = selb00;
        end
        2'b01:begin//(read a,write b) ,write b first
		      cena00 = 1'b0;
	        cenb00 = selb00;
        end
        2'b10:begin//(write a,read b) ,write a first
		      cena00 = sela00;
	        cenb00 = 1'b0;
        end
        2'b11:begin//(write a&b) ,write a first
		      cena00 = sela00;
	        cenb00 = 1'b0;
        end
	      default:begin
		      cena00 = sela00;
	        cenb00 = selb00;
        end
      endcase
    end
    else begin
         cena00 = sela00;//1'b0;
	       cenb00 = selb00;//1'b0;
    end
  end

ram_dp_d512_w128 U00_ram_dp_d512_w128(
.CENYA(),
.WENYA(),
.AYA(),
.CENYB(),
.WENYB(),
.AYB(),
.QA(),
.QB(doutb00),
.SOA(),
.SOB(),
.CLKA(clka),
.CENA(~cena00),
.WENA(~wea),
.AA(addra[8:0]),
.DA(dina),
.CLKB(clkb),
.CENB(~cenb00),
.WENB(1'b1),        //(~web00),
.AB(addrb[8:0]),
.DB(dinb),
.EMAA(ram_dp_cfg_register[11:9]),
.EMAWA(ram_dp_cfg_register[8:7]),
.EMASA(ram_dp_cfg_register[6]),
.EMAB(ram_dp_cfg_register[5:3]),
.EMAWB(ram_dp_cfg_register[2:1]),
.EMASB(ram_dp_cfg_register[0]),
.TENA(1'b1),
.TCENA(1'b1),
.TWENA(1'b1),
.TAA(9'b0),
.TDA(128'b0),
.TENB(1'b1),
.TCENB(1'b1),
.TWENB(1'b1),
.TAB(9'b0),
.TDB(128'b0),
.RET1N(1'b1),
.SIA(2'b1),
.SEA(1'b0),
.DFTRAMBYP(1'b0),
.SIB(2'b1),
.SEB(1'b0),
.COLLDISN(1'b1) 
);

  //wirte first
  always@(*)begin
    if((addra == addrb))begin
      case({wea,web}) 
	      2'b00:begin//(rd a&b) 
		      cena01 = sela01;
	        cenb01 = selb01;
        end
        2'b01:begin//(read a,wirte b) ,wirt b first
		      cena01 = 1'b1;
	        cenb01 = selb01;
        end
        2'b10:begin//(wirte a,read b) ,wirt a first
		      cena01 = sela01;
	        cenb01 = 1'b1;
        end
        2'b11:begin//(wirte a&b) ,wirt a first
		      cena01 = sela01;
	        cenb01 = 1'b1;
        end
	      default:begin
		      cena01 = sela01;
	        cenb01 = selb01;
        end
      endcase
    end
    else begin
         cena01 = sela01;
	       cenb01 = selb01;
    end
  end

ram_dp_d512_w128 U01_ram_dp_d512_w128(
.CENYA(),
.WENYA(),
.AYA(),
.CENYB(),
.WENYB(),
.AYB(),
.QA(),
.QB(doutb01),
.SOA(),
.SOB(),
.CLKA(clka),
.CENA(~cena01),
.WENA(~wea),
.AA(addra[8:0]),
.DA(dina),
.CLKB(clkb),
.CENB(~cenb01),
.WENB(1'b1),        //(~web01),
.AB(addrb[8:0]),
.DB(dinb),
.EMAA(ram_dp_cfg_register[11:9]),
.EMAWA(ram_dp_cfg_register[8:7]),
.EMASA(ram_dp_cfg_register[6]),
.EMAB(ram_dp_cfg_register[5:3]),
.EMAWB(ram_dp_cfg_register[2:1]),
.EMASB(ram_dp_cfg_register[0]),
.TENA(1'b1),
.TCENA(1'b1),
.TWENA(1'b1),
.TAA(9'b0),
.TDA(128'b0),
.TENB(1'b1),
.TCENB(1'b1),
.TWENB(1'b1),
.TAB(9'b0),
.TDB(128'b0),
.RET1N(1'b1),
.SIA(2'b1),
.SEA(1'b0),
.DFTRAMBYP(1'b0),
.SIB(2'b1),
.SEB(1'b0),
.COLLDISN(1'b1) 
);

  //wirte first
  always@(*)begin
    if((addra == addrb))begin
      case({wea,web}) 
	      2'b00:begin//(rd a&b) 
		      cena10 = sela10;
	        cenb10 = selb10;
        end
        2'b01:begin//(read a,wirte b) ,wirt b first
		      cena10 = 1'b1;
	        cenb10 = selb10;
        end
        2'b10:begin//(wirte a,read b) ,wirt a first
		      cena10 = sela10;
	        cenb10 = 1'b1;
        end
        2'b11:begin//(wirte a&b) ,wirt a first
		      cena10 = sela10;
	        cenb10 = 1'b1;
        end
	      default:begin
		      cena10 = sela10;
	        cenb10 = selb10;
        end
      endcase
    end
    else begin
         cena10 = sela10;
	       cenb10 = selb10;
    end
  end

ram_dp_d512_w128 U10_ram_dp_d512_w128(
.CENYA(),
.WENYA(),
.AYA(),
.CENYB(),
.WENYB(),
.AYB(),
.QA(),
.QB(doutb10),
.SOA(),
.SOB(),
.CLKA(clka),
.CENA(~cena10),
.WENA(~wea),
.AA(addra[8:0]),
.DA(dina),
.CLKB(clkb),
.CENB(~cenb10),
.WENB(1'b1),        //(~web10),
.AB(addrb[8:0]),
.DB(dinb),
.EMAA(ram_dp_cfg_register[11:9]),
.EMAWA(ram_dp_cfg_register[8:7]),
.EMASA(ram_dp_cfg_register[6]),
.EMAB(ram_dp_cfg_register[5:3]),
.EMAWB(ram_dp_cfg_register[2:1]),
.EMASB(ram_dp_cfg_register[0]),
.TENA(1'b1),
.TCENA(1'b1),
.TWENA(1'b1),
.TAA(9'b0),
.TDA(128'b0),
.TENB(1'b1),
.TCENB(1'b1),
.TWENB(1'b1),
.TAB(9'b0),
.TDB(128'b0),
.RET1N(1'b1),
.SIA(2'b1),
.SEA(1'b0),
.DFTRAMBYP(1'b0),
.SIB(2'b1),
.SEB(1'b0),
.COLLDISN(1'b1) 
);

  //wirte first
  always@(*)begin
    if((addra == addrb))begin
      case({wea,web}) 
	      2'b00:begin//(rd a&b) 
		      cena11 = sela11;
	        cenb11 = selb11;
        end
        2'b01:begin//(read a,wirte b) ,wirt b first
		      cena11 = 1'b1;
	        cenb11 = selb11;
        end
        2'b10:begin//(wirte a,read b) ,wirt a first
		      cena11 = sela11;
	        cenb11 = 1'b1;
        end
        2'b11:begin//(wirte a&b) ,wirt a first
		      cena11 = sela11;
	        cenb11 = 1'b1;
        end
	      default:begin
		      cena11 = sela11;
	        cenb11 = selb11;
        end
      endcase
    end
    else begin
         cena11 = sela11;
	       cenb11 = selb11;
    end
  end

ram_dp_d512_w128 U11_ram_dp_d512_w128(
.CENYA(),
.WENYA(),
.AYA(),
.CENYB(),
.WENYB(),
.AYB(),
.QA(),
.QB(doutb11),
.SOA(),
.SOB(),
.CLKA(clka),
.CENA(~cena11),
.WENA(~wea),
.AA(addra[8:0]),
.DA(dina),
.CLKB(clkb),
.CENB(~cenb11),
.WENB(1'b1),        //(~web11),
.AB(addrb[8:0]),
.DB(dinb),
.EMAA(ram_dp_cfg_register[11:9]),
.EMAWA(ram_dp_cfg_register[8:7]),
.EMASA(ram_dp_cfg_register[6]),
.EMAB(ram_dp_cfg_register[5:3]),
.EMAWB(ram_dp_cfg_register[2:1]),
.EMASB(ram_dp_cfg_register[0]),
.TENA(1'b1),
.TCENA(1'b1),
.TWENA(1'b1),
.TAA(9'b0),
.TDA(128'b0),
.TENB(1'b1),
.TCENB(1'b1),
.TWENB(1'b1),
.TAB(9'b0),
.TDB(128'b0),
.RET1N(1'b1),
.SIA(2'b1),
.SEA(1'b0),
.DFTRAMBYP(1'b0),
.SIB(2'b1),
.SEB(1'b0),
.COLLDISN(1'b1) 
);
endmodule
